package service;

import com.alibaba.excel.EasyExcel;
import com.twitter.penguin.korean.*;
import com.twitter.penguin.korean.tokenizer.KoreanTokenizer;
import javafx.util.Pair;
import me.xdrop.diffutils.DiffUtils;
import me.xdrop.fuzzywuzzy.FuzzySearch;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import scala.collection.Seq;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

import static io.ExcelUtil.getCellFromRowByIndex;

/**
 * Created by fanzhenyu02 on 2022/6/08.
 */
public class FuzzyMatchingService {


    public static List<List<Object>> matchResultList = new ArrayList<>();
    public static List<List<Object>> bypassResultList = new ArrayList<>();


    public static void main(String[] args) throws Exception {
        long startExecuteTime = System.currentTimeMillis();


//        List<Product> approvedCaseList = loadRealCaseList("/Users/zhfan/Downloads/rejected.csv");

        final List<String> includingKeywordList = readIncludingKeywordList();
        final List<String> excludingKeywordList = readExcludingKeywordList();

        List<Product> candidateList = readCandidateProduct(200000);
        int counter = 0, totalSize = 0;
        for (Product product : candidateList) {
            totalSize++;
            if (!isGatedByBrandContainMatch(product, includingKeywordList, excludingKeywordList)) {
//                System.out.println(product);
                List<Object> data = new ArrayList<>();
                data.add(product.getVendorItemId());
                data.add(product.getProductName());
                data.add(product.getBrand());
                data.add("");
                bypassResultList.add(data);
                counter++;
            }
        }

        EasyExcel.write("/Users/zhfan/Downloads/contains_match_matched_result_20220617_02.xlsx").head(generateMatchHead()).sheet("matched_result").doWrite(matchResultList);
        EasyExcel.write("/Users/zhfan/Downloads/contains_match_bypass_result_20220617_02.xlsx").head(generateMatchHead()).sheet("bypass_result").doWrite(bypassResultList);
        System.out.println("\ntotal " + counter + " products did not catch, and precision is : " + (100.0 - counter * 100.0 / totalSize) + " % ");

        System.out.println("\ncurrent solution total execute time: " + (System.currentTimeMillis() - startExecuteTime) + " ms.");
    }

    //    /Users/zhfan/Downloads/approved.csv
    public static List<Product> loadRealCaseList(String fileName) {
        BufferedReader br = null;
        String line = "";
        List<Product> candidateList = new ArrayList<>();

        try {
            br = new BufferedReader(new FileReader(fileName));
            while ((line = br.readLine()) != null) {
                if (StringUtils.isBlank(line) || line.length() <= 4) continue;
                String vendorItemId = line.substring(line.indexOf("id=") + 3, line.indexOf(", brand="));
                String brand = line.substring(line.indexOf(", brand=") + 8, line.indexOf(", productTitle="));
                String productName = line.substring(line.indexOf("productTitle=") + 13, line.length());
                Product product = Product.builder()
                        .vendorItemId(vendorItemId)
                        .brand(brand)
                        .productName(productName)
                        .build();
                candidateList.add(product);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return candidateList;
    }


    public static List<KoreanTokenJava> splitKeyword(String str) {
        // Normalize
        CharSequence normalized = TwitterKoreanProcessorJava.normalize(str);

        // Tokenize
        Seq<KoreanTokenizer.KoreanToken> tokens = TwitterKoreanProcessorJava.tokenize(normalized);
        return TwitterKoreanProcessorJava.tokensToJavaKoreanTokenList(tokens);// 可以添加filter，过滤掉形容词
    }

    /**
     * 参考文档：https://blog.csdn.net/qq_32447301/article/details/107269350
     *
     * @param source
     * @param target
     * @return
     */
    public static boolean isFuzzyMatch(String source, String target) {
        final int score = FuzzySearch.tokenSortRatio(source, target);
        return score >= 65; // 首先做排序，然后全匹配，对顺序不敏感(也就是更换单词位置之后，相似度依然会很高)
    }

    public static final int excludeThreshold = 1;

    public static boolean isGatedByBrand(Product product, List<String> includingKeywordList, List<String> excludingKeywordList) {
        // check if match including keyword
        String matchIncludeKeyword = null;
        for (String includingKeyword : includingKeywordList) {
            if (isFuzzyMatch(product.brand, includingKeyword)) {
                matchIncludeKeyword = includingKeyword;
                break;
            }
        }

        if (null == matchIncludeKeyword) return false; // no match any including Keywords

        // third check if match excluding keyword
        List<String> matchExcludeKeywordList = new ArrayList<>();
        for (String excludingKeyword : excludingKeywordList) {
            if (isFuzzyMatch(product.brand, excludingKeyword)) {
                matchExcludeKeywordList.add(excludingKeyword);
                if (matchExcludeKeywordList.size() >= excludeThreshold) break;
            }
        }

        if (matchExcludeKeywordList.size() < excludeThreshold) {
            List<Object> data = new ArrayList<>();
            data.add(product.getVendorItemId());
            data.add(product.getProductName());
            data.add(product.getBrand());
            data.add(matchIncludeKeyword);
            matchResultList.add(data);
        }

        return matchExcludeKeywordList.size() < excludeThreshold; // exclude match Keywords cannot be so much.
    }

    public static boolean isGatedByProduct(Product product, List<String> includingKeywordList, List<String> excludingKeywordList) {
        // first split targetValue
        List<KoreanTokenJava> splitKoreanTokenList = splitKeyword(product.productName);

        // second check if match including keyword
        String matchIncludeKeyword = null;
        for (KoreanTokenJava koreanTokenJava : splitKoreanTokenList) {
            if (null != matchIncludeKeyword) break;
            for (String includingKeyword : includingKeywordList) {
                if (isFuzzyMatch(koreanTokenJava.getText(), includingKeyword)) {
                    matchIncludeKeyword = includingKeyword;
                    break;
                }
            }
        }

        if (null == matchIncludeKeyword) return false; // no match any including Keywords

        // third check if match excluding keyword
        List<String> matchExcludeKeywordList = new ArrayList<>();
        for (KoreanTokenJava koreanTokenJava : splitKoreanTokenList) {
            if (matchExcludeKeywordList.size() >= excludeThreshold) break;
            for (String excludingKeyword : excludingKeywordList) {
                if (isFuzzyMatch(koreanTokenJava.getText(), excludingKeyword)) {
                    matchExcludeKeywordList.add(excludingKeyword);
                    if (matchExcludeKeywordList.size() >= excludeThreshold) break;
                }
            }
        }

        return matchExcludeKeywordList.size() < 2; // exclude match Keywords cannot be so much.
    }

    public static boolean isGatedByBrandContainMatch(Product product, List<String> includingKeywordList, List<String> excludingKeywordList) {
        String matchIncludeKeyword = null;
        for (String includingKeyword : includingKeywordList) {
            if (product.brand.toLowerCase(Locale.KOREAN).contains(includingKeyword.toLowerCase(Locale.KOREAN))) {
                matchIncludeKeyword = includingKeyword;
                break;
            }
        }

        if (null == matchIncludeKeyword) return false; // no match any including Keywords

        // third check if match excluding keyword
        List<String> matchExcludeKeywordList = new ArrayList<>();
        for (String excludingKeyword : excludingKeywordList) {
            if (product.brand.toLowerCase(Locale.KOREAN).contains(excludingKeyword.toLowerCase(Locale.KOREAN))) {
                matchExcludeKeywordList.add(excludingKeyword);
                if (matchExcludeKeywordList.size() >= excludeThreshold) break;
            }
        }

        if (matchExcludeKeywordList.size() < excludeThreshold) {
            List<Object> data = new ArrayList<>();
            data.add(product.getVendorItemId());
            data.add(product.getProductName());
            data.add(product.getBrand());
            data.add(matchIncludeKeyword);
            matchResultList.add(data);
        }

        return matchExcludeKeywordList.size() < excludeThreshold; // exclude match Keywords cannot be so much.
    }


    private static List<List<String>> generateMatchHead() {
        List<List<String>> list = new ArrayList<>();
        List<String> head0 = new ArrayList<>();
        head0.add("vendorItemid");

        List<String> head1 = new ArrayList<>();
        head1.add("productName");

        List<String> head2 = new ArrayList<>();
        head2.add("brand");

        List<String> head3 = new ArrayList<>();
        head3.add("gatedBrandKeyword");


        list.add(head0);
        list.add(head1);
        list.add(head2);
        list.add(head3);
        return list;
    }


    public static void printFuzzyScore(String source, String target) {
        int score = FuzzySearch.tokenSortRatio(source, target);
        System.out.println(source + " and " + target + " fuzzyScore is : " + score);
    }


    public static List<Product> readCandidateProduct(int targetSize) {
        List<Product> candidateList = new ArrayList<>();
        try {
            Workbook workbook = WorkbookFactory.create(new File("/Users/zhfan/Downloads/target_data.xlsx"));
            Sheet sheet = workbook.getSheetAt(1);
            for (Row row : sheet) {
                if (StringUtils.isBlank(getCellFromRowByIndex(row, 0))) continue;
                Product product = Product.builder()
                        .vendorItemId(getCellFromRowByIndex(row, 0))
                        .productName(getCellFromRowByIndex(row, 1))
                        .brand(getCellFromRowByIndex(row, 2))
                        .build();
                candidateList.add(product);
                if (candidateList.size() >= targetSize) break;
            }
        } catch (Exception e) {
            System.err.println("readExcelFile got error!" + e);
        }

        return candidateList;
    }

    public static List<Pair<String, String>> readCSV() {
        BufferedReader br = null;
        String line = "";
        List<Pair<String, String>> candidateList = new ArrayList<>();

        try {
            br = new BufferedReader(new FileReader("/Users/zhfan/Downloads/target_data.csv"));
            while ((line = br.readLine()) != null) {
                if (StringUtils.isBlank(line) || line.length() <= 4 || !line.contains(",\"")) continue;
                String[] rowSplit = line.split(",\"");
                String productName = rowSplit[1].split("\",")[0];
                String brand = rowSplit[1].split("\",")[1];
                candidateList.add(new Pair<>(rowSplit[0], productName));
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return candidateList;
    }

    public static List<String> readIncludingKeywordList() {
        BufferedReader br = null;
        String line = "";
        List<String> includingKeywordList = new ArrayList<>();

        try {
            br = new BufferedReader(new FileReader("/Users/zhfan/Downloads/including_keyword.txt"));
            while ((line = br.readLine()) != null) {
                if (StringUtils.isBlank(line)) continue;
                includingKeywordList.add(line);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return includingKeywordList;
    }

    public static List<String> readExcludingKeywordList() {
        BufferedReader br = null;
        String line = "";
        List<String> excludingKeywordList = new ArrayList<>();

        try {
            br = new BufferedReader(new FileReader("/Users/zhfan/Downloads/excluding_keyword.txt"));
            while ((line = br.readLine()) != null) {
                if (StringUtils.isBlank(line)) continue;
                excludingKeywordList.add(line);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return excludingKeywordList;
    }


    public static void fuzzyMatchTest() {
        System.out.println("1 " + FuzzySearch.ratio("admin", "admin"));
        System.out.println("2 " + FuzzySearch.partialRatio("ADMIN", "admin"));
        System.out.println("3 " + FuzzySearch.tokenSetPartialRatio("test", "test1"));
        System.out.println("4 " + FuzzySearch.weightedRatio("你是", "你是我"));
        System.out.println("5 " + FuzzySearch.tokenSortRatio("你是", "你是W"));
        System.out.println("6 " + FuzzySearch.tokenSetRatio("你是", "你是o"));
        System.out.println(DiffUtils.getRatio("你是", "你是我"));
        System.out.println(DiffUtils.levEditDistance("你是", "你是我", 1));
        System.out.println(DiffUtils.getMatchingBlocks("你是", "你是我"));
        System.out.println(DiffUtils.getEditOps("你是", "你是我"));

        printFuzzyScore("Rockshox Lyrik", "RockshoxLyrik");
        printFuzzyScore("Rockshox Lyrik", "RockshoxLyrik");
        printFuzzyScore("Rockshox Lyrik", "RockshoxLyrika");
        printFuzzyScore("Rockshox Lyrik", "Rockshox Lyrik test");
        printFuzzyScore("Rockshox Lyrik", "+%Rockshox Lyrik &5");
        printFuzzyScore("Rockshox Lyrik", "+%Rockshox_Lyrik &5");
        printFuzzyScore("Rockshox Lyrik", "+%Rockshox_8Lyrik &5");
        printFuzzyScore("애플", "애플");
        printFuzzyScore("애플", "c애플");
        printFuzzyScore("애플", "c애플+");
    }

    public static List<String> generateForbiddenKeywordList() {
        return Arrays.asList("포드", "도요타", "BWM", "벤츠", "testkey", "how your");
    }

    public static List<String> generateCandidateTestList() {
        List<String> candidateList = new ArrayList<>();
        candidateList.add("Brand=협력업체, 1645853926429, productName=XINMORE 14.6V 25A Lifepo4 리튬 배터리 충전기 12V 4S 전원 폴리머 스쿠터 Ebike, displayProductName=XINMORE 14.6V 25A Lifepo4 리튬 배터리 충전기 12V 4S 전원 폴리머 스쿠터 Ebike, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=협력업체, 1645855782370, productName=16S 58.4V 4A 지능형 배터리 충전기 48V 51.2V-52VLifePO4 배터리 팩 전기 자전거 스쿠터 빠른 스마트 충전기, displayProductName=16S 58.4V 4A 지능형 배터리 충전기 48V 51.2V-52VLifePO4 배터리 팩 전기 자전거 스쿠터 빠른 스마트 충전기, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=unknown, 1649173533963, productName=Kawaii 핸드 계정 재료 Scrapbooking 세트 선물 상자 Ins 바람 장식 귀여운 보라색 핑크 일기 테이프 용품 학교, displayProductName=Kawaii 핸드 계정 재료 Scrapbooking 세트 선물 상자 Ins 바람 장식 귀여운 보라색 핑크 일기 테이프 용품 학교, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=unknown, 1653397470372, productName=2022 Rockshox Lyrik 프론트 포크 스티커 산악 자전거 방수 장식 наклейки на велосипед, displayProductName=2022 Rockshox Lyrik 프론트 포크 스티커 산악 자전거 방수 장식 наклейки на велосипед, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=상세페이지참조, 1654479092484, productName=100M 252 색 파라코드 550 낙하산 코드 로프, 7 가닥 파라코드 야외 캠핑 생존 파라코드 로프, displayProductName=100M 252 색 파라코드 550 낙하산 코드 로프, 7 가닥 파라코드 야외 캠핑 생존 파라코드 로프, generalProductName=, manufacture=상세페이지참조");
        candidateList.add("Brand=베스트상품, 1625305631680, productName=BMW 5시리즈 E60 E61 F10 F11 520D 525D 528D 530D 535D 538D 520I 530I 후면 트렁크 엠블렘, displayProductName=BMW 5시리즈 E60 E61 F10 F11 520D 525D 528D 530D 535D 538D 520I 530I 후면 트렁크 엠블렘, generalProductName=BMW 5시리즈 E60 E61 F10 F11 520D 525D 528D 530D 535D 538D 520I 530I 후면 트렁크 엠블렘, manufacture=베스트선정아이템");
        candidateList.add("Brand=unknown, 1653453595228, productName=버트 캡/짐벌 커버 16 #/20 #/23.5 #/25 #/27.5 #/30 # 소프트 캡 낚싯대 엔드, displayProductName=버트 캡/짐벌 커버 16 #/20 #/23.5 #/25 #/27.5 #/30 # 소프트 캡 낚싯대 엔드, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=베스트상품, 1616642657140, productName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, displayProductName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, generalProductName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, manufacture=베스트선정아이템");
        candidateList.add("Brand=베스트상품, 1618833925810, productName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, displayProductName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, generalProductName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, manufacture=베스트선정아이템");
        candidateList.add("Brand=협력업체, 1645321694660, productName=양쯔-리튬 배터리 충전기 84V 2.5A 리튬 이온 자동차 72V 지능형 리포 자전거 전동 공구 전기 자전거 배터리 팩, displayProductName=양쯔-리튬 배터리 충전기 84V 2.5A 리튬 이온 자동차 72V 지능형 리포 자전거 전동 공구 전기 자전거 배터리 팩, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=unknown, 1653453595228, productName=버트 캡/짐벌 커버 16 #/20 #/23.5 #/25 #/27.5 #/30 # 소프트 캡 낚싯대 엔드, displayProductName=버트 캡/짐벌 커버 16 #/20 #/23.5 #/25 #/27.5 #/30 # 소프트 캡 낚싯대 엔드, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=협력업체, 1649150770618, productName=12 V 50.4V 1.5A 2A 지능형 리튬 배터리 충전기 43.2V 43.8V 44.4V 48V Lypomer 리튬 이온 배터리 팩, displayProductName=12 V 50.4V 1.5A 2A 지능형 리튬 배터리 충전기 43.2V 43.8V 44.4V 48V Lypomer 리튬 이온 배터리 팩, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=베스트상품, 1624276278591, productName=56mm 스티커  20개 56cm 데칼  혼다 현대 재규어 지프 닛산 볼보 기아, displayProductName=56mm 스티커  20개 56cm 데칼  혼다 현대 재규어 지프 닛산 볼보 기아, generalProductName=56mm 스티커  20개 56cm 데칼  혼다 현대 재규어 지프 닛산 볼보 기아, manufacture=베스트선정아이템");
        candidateList.add("Brand=협력업체, 1654476895407, productName=전기 자전거에 대 한 48V 5A 전자 bikeo 배터리 도구에 대 한 양쯔강 54.6V 5A 리튬 배터리 충전기, displayProductName=전기 자전거에 대 한 48V 5A 전자 bikeo 배터리 도구에 대 한 양쯔강 54.6V 5A 리튬 배터리 충전기, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=협력업체, productName=58.8V 4A 14S CE ROHS 리튬 배터리 충전기 14S 48V 51.8V 52V 리튬 이온 배터리 팩 Lipo 자동차 전기 자전거 AC100V-240V, displayProductName=58.8V 4A 14S CE ROHS 리튬 배터리 충전기 14S 48V 51.8V 52V 리튬 이온 배터리 팩 Lipo 자동차 전기 자전거 AC100V-240V, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=협력업체, 1645853087058, productName=50.4V 4A 12S Lipo 자동차 리튬 배터리 충전기 44.4V 리튬 이온 배터리 전기 자전거 자전거 스쿠터 CE ROHS 빠른 충전기, displayProductName=50.4V 4A 12S Lipo 자동차 리튬 배터리 충전기 44.4V 리튬 이온 배터리 전기 자전거 자전거 스쿠터 CE ROHS 빠른 충전기, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=unknown, 1652291196576, productName=2022 Rockshox Lyrik 프론트 포크 스티커 산악 자전거 방수 장식 наклейки на велосипед, displayProductName=2022 Rockshox Lyrik 프론트 포크 스티커 산악 자전거 방수 장식 наклейки на велосипед, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=베스트상품, 1618833936819, productName=로고 재떨이 LED 조명등나푸른 조명등 아우디 A1 A3 A4 A5 A6 Q3 Q5 8V Q7 C5 B8 A8, displayProductName=로고 재떨이 LED 조명등나푸른 조명등 아우디 A1 A3 A4 A5 A6 Q3 Q5 8V Q7 C5 B8 A8, generalProductName=로고 재떨이 LED 조명등나푸른 조명등 아우디 A1 A3 A4 A5 A6 Q3 Q5 8V Q7 C5 B8 A8, manufacture=베스트선정아이템");
        candidateList.add("Brand=협력업체, 1645854226265, productName=YZPOWER 자동 정지 50.4V 6A 리튬 배터리 충전기 44.4V 리튬 이온 Lipo 배터리 팩 Ebike 전자 자전거 도구, displayProductName=YZPOWER 자동 정지 50.4V 6A 리튬 배터리 충전기 44.4V 리튬 이온 Lipo 배터리 팩 Ebike 전자 자전거 도구, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=베스트상품, 1625036530368, productName=2개 가죽 로고 키 귀하 사랑로고 링 기아 아우디 BMW 벤츠 혼다 지프, displayProductName=2개 가죽 로고 키 귀하 사랑로고 링 기아 아우디 BMW 벤츠 혼다 지프, generalProductName=2개 가죽 로고 키 귀하 사랑로고 링 기아 아우디 BMW 벤츠 혼다 지프, manufacture=베스트선정아이템");
        candidateList.add("Brand=베스트상품, 1618833935866, productName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, displayProductName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, generalProductName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, manufacture=베스트선정아이템");
        candidateList.add("Brand=베스트상품, 1616642657140, productName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, displayProductName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, generalProductName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, manufacture=베스트선정아이템");
        candidateList.add("Brand=협력업체, 1645855782370, productName=16S 58.4V 4A 지능형 배터리 충전기 48V 51.2V-52VLifePO4 배터리 팩 전기 자전거 스쿠터 빠른 스마트 충전기, displayProductName=16S 58.4V 4A 지능형 배터리 충전기 48V 51.2V-52VLifePO4 배터리 팩 전기 자전거 스쿠터 빠른 스마트 충전기, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=unknown, 1653453595228, productName=버트 캡/짐벌 커버 16 #/20 #/23.5 #/25 #/27.5 #/30 # 소프트 캡 낚싯대 엔드, displayProductName=버트 캡/짐벌 커버 16 #/20 #/23.5 #/25 #/27.5 #/30 # 소프트 캡 낚싯대 엔드, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=베스트상품, 1620120899093, productName=로고 시트로엥 C1 C5 DS5 시트로엥 C4 그랜드 매트, displayProductName=로고 시트로엥 C1 C5 DS5 시트로엥 C4 그랜드 매트, generalProductName=로고 시트로엥 C1 C5 DS5 시트로엥 C4 그랜드 매트, manufacture=베스트선정아이템");
        candidateList.add("Brand=협력업체, 1645854360848, productName=양쯔강 리튬 이온 충전기 84V 5A 72V 20S 자동차 리튬 배터리 충전기 배터리 Voiture 지능형 리튬 이온 폴리머 Ebike, displayProductName=양쯔강 리튬 이온 충전기 84V 5A 72V 20S 자동차 리튬 배터리 충전기 배터리 Voiture 지능형 리튬 이온 폴리머 Ebike, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=unknown, 1645704330451, productName=252 색상 50 M 스풀 파라코드 550 로프 유형 III 7 스탠드 낙하산 코드 야외 캠핑 생존 바람 도매 스포츠 아웃도어 활동 엔터테인먼트 액티비티 안전한 내구성, displayProductName=252 색상 50 M 스풀 파라코드 550 로프 유형 III 7 스탠드 낙하산 코드 야외 캠핑 생존 바람 도매 스포츠 아웃도어 활동 엔터테인먼트 액티비티 안전한 내구성, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=unknown, 1653756226471, productName=장식 페인트 롤러 패턴 양각 질감 그림 도구 벽 에어리스 Pintura 기계 가정용 브러시 고무 324T, displayProductName=장식 페인트 롤러 패턴 양각 질감 그림 도구 벽 에어리스 Pintura 기계 가정용 브러시 고무 324T, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=unknown, 1653454858590, productName=MN 팁 탑 #5 낚싯대 수리 가이드 10 pcs 5 #., displayProductName=MN 팁 탑 #5 낚싯대 수리 가이드 10 pcs 5 #., generalProductName=, manufacture=unknown");
        candidateList.add("Brand=unknown, 1650828611980, productName=알루미늄 플럼 플렉시블 샤프트 커플 링 D40 L55 모터 커넥터 커플러 8mm ~ 22mm D40L55 91012716mm, displayProductName=알루미늄 플럼 플렉시블 샤프트 커플 링 D40 L55 모터 커넥터 커플러 8mm ~ 22mm D40L55 91012716mm, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=unknown, 1645304356235, productName=블랙 100 미터 로프 파라코드 야외 7 가닥 코드 폴리 프로필렌 550 생존 꼰 팔찌, displayProductName=블랙 100 미터 로프 파라코드 야외 7 가닥 코드 폴리 프로필렌 550 생존 꼰 팔찌, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=unknown, 1653532447220, productName=플렉시블 플럼 클램프 커플러 D45 L66 샤프트 크기 죠 커플 링 101214161820222425mm, displayProductName=플렉시블 플럼 클램프 커플러 D45 L66 샤프트 크기 죠 커플 링 101214161820222425mm, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=베스트상품, 1628163170236, productName=4개 점화 플러그 F10 F30 F07 F15 F25 BMW 3 5 X3 X5 7 시리즈 12120037664 엔진 도구, displayProductName=4개 점화 플러그 F10 F30 F07 F15 F25 BMW 3 5 X3 X5 7 시리즈 12120037664 엔진 도구, generalProductName=4개 점화 플러그 F10 F30 F07 F15 F25 BMW 3 5 X3 X5 7 시리즈 12120037664 엔진 도구, manufacture=베스트선정아이템");
        candidateList.add("Brand=베스트상품, 1628163170236, productName=4개 점화 플러그 F10 F30 F07 F15 F25 BMW 3 5 X3 X5 7 시리즈 12120037664 엔진 도구, displayProductName=4개 점화 플러그 F10 F30 F07 F15 F25 BMW 3 5 X3 X5 7 시리즈 12120037664 엔진 도구, generalProductName=4개 점화 플러그 F10 F30 F07 F15 F25 BMW 3 5 X3 X5 7 시리즈 12120037664 엔진 도구, manufacture=베스트선정아이템");
        candidateList.add("Brand=베스트상품, 1618833925810, productName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, displayProductName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, generalProductName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, manufacture=베스트선정아이템");
        candidateList.add("Brand=베스트상품, 1624279671422, productName=데칼 56cm 스티커 56mm 20개  혼다 현대 재규어 지프 닛산 볼보 기아, displayProductName=데칼 56cm 스티커 56mm 20개  혼다 현대 재규어 지프 닛산 볼보 기아, generalProductName=데칼 56cm 스티커 56mm 20개  혼다 현대 재규어 지프 닛산 볼보 기아, manufacture=베스트선정아이템");
        candidateList.add("Brand=협력업체, 1649149505968, productName=YZPOWER 100V240V 67.2V 5A 리튬 배터리 충전기 60V 전자 자전거 세발 자전거 자동차 빠른 충전기, displayProductName=YZPOWER 100V240V 67.2V 5A 리튬 배터리 충전기 60V 전자 자전거 세발 자전거 자동차 빠른 충전기, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=unknown, 1652520645032, productName=장식 페인트 롤러 패턴 양각 질감 그림 도구 벽 에어리스 Pintura 기계 가정용 브러시 고무 324T, displayProductName=장식 페인트 롤러 패턴 양각 질감 그림 도구 벽 에어리스 Pintura 기계 가정용 브러시 고무 324T, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=협력업체, 1645319127835, productName=12V 리튬 배터리에 대 한 양쯔강 12.6V 8A 배터리 충전기 전기 자전거에 대 한 전기 자전거 전원 전기 도구, displayProductName=12V 리튬 배터리에 대 한 양쯔강 12.6V 8A 배터리 충전기 전기 자전거에 대 한 전기 자전거 전원 전기 도구, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=베스트상품, 1620120653407, productName=로고 시트로엥 C1 C5 DS5 시트로엥 C4 그랜드 매트, displayProductName=로고 시트로엥 C1 C5 DS5 시트로엥 C4 그랜드 매트, generalProductName=로고 시트로엥 C1 C5 DS5 시트로엥 C4 그랜드 매트, manufacture=베스트선정아이템");
        candidateList.add("Brand=협력업체, 1649149732299, productName=CE rohs와 50.4V 리튬 이온 폴리머 스쿠터 전자 자전거 ebike에 대 한 양쯔강 44.4V 8A 리튬 배터리 충전기, displayProductName=CE rohs와 50.4V 리튬 이온 폴리머 스쿠터 전자 자전거 ebike에 대 한 양쯔강 44.4V 8A 리튬 배터리 충전기, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=협력업체, 1649150031834, productName=CE rohs와 50.4V 리튬 이온 폴리머 팩 Lipo 전기 자전거 스쿠터 전자 자전거 자전거에 대 한 12S 44.4V 8A 자동차 리튬 배터리 충전기, displayProductName=CE rohs와 50.4V 리튬 이온 폴리머 팩 Lipo 전기 자전거 스쿠터 전자 자전거 자전거에 대 한 12S 44.4V 8A 자동차 리튬 배터리 충전기, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=베스트상품, 1622198775322, productName=인기  포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, displayProductName=인기  포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, generalProductName=인기  포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, manufacture=베스트선정아이템");
        candidateList.add("Brand=협력업체, 1645854185381, productName=양쯔강 50.4V 4A 리튬 이온 배터리 충전기 12S 44.4V Lipo 자전거 전원 도구 스쿠터 배터리 팩 CE ROHS, displayProductName=양쯔강 50.4V 4A 리튬 이온 배터리 충전기 12S 44.4V Lipo 자전거 전원 도구 스쿠터 배터리 팩 CE ROHS, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=unknown, 1653453595228, productName=버트 캡/짐벌 커버 16 #/20 #/23.5 #/25 #/27.5 #/30 # 소프트 캡 낚싯대 엔드, displayProductName=버트 캡/짐벌 커버 16 #/20 #/23.5 #/25 #/27.5 #/30 # 소프트 캡 낚싯대 엔드, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=베스트상품, 1616642657241, productName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, displayProductName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, generalProductName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, manufacture=베스트선정아이템");
        candidateList.add("Brand=베스트상품, 1624279673555, productName=휠 56mm 56cm 알루미늄 20X  데칼 BMW 도요타 혼다 현대 재규어 지프 닛산 볼보, displayProductName=휠 56mm 56cm 알루미늄 20X  데칼 BMW 도요타 혼다 현대 재규어 지프 닛산 볼보, generalProductName=휠 56mm 56cm 알루미늄 20X  데칼 BMW 도요타 혼다 현대 재규어 지프 닛산 볼보, manufacture=베스트선정아이템");
        candidateList.add("Brand=협력업체, 1645318724345, productName=72V 전자 자전거 리튬 이온 배터리 팩에 대 한 XINMORE 84V 10A 리튬 배터리 충전기 전기 도구에 대 한 AC-DC 전원 공급 장치, displayProductName=72V 전자 자전거 리튬 이온 배터리 팩에 대 한 XINMORE 84V 10A 리튬 배터리 충전기 전기 도구에 대 한 AC-DC 전원 공급 장치, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=베스트상품, 1618833925810, productName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, displayProductName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, generalProductName=로고 재떨이 A3 A4 A5 A6 A7 A8 B8 B9 C5 C6 C7 Q3 Q5 Q7, manufacture=베스트선정아이템");
        candidateList.add("Brand=협력업체, 1649150770618, productName=12 V 50.4V 1.5A 2A 지능형 리튬 배터리 충전기 43.2V 43.8V 44.4V 48V Lypomer 리튬 이온 배터리 팩, displayProductName=12 V 50.4V 1.5A 2A 지능형 리튬 배터리 충전기 43.2V 43.8V 44.4V 48V Lypomer 리튬 이온 배터리 팩, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=협력업체, 1649149118164, productName=SkyRC e430 충전기 2-4 셀 1A 2A 3A 200mA Lipo LiFe 충전기 100-240v AC 밸런스 충전기 30W, displayProductName=SkyRC e430 충전기 2-4 셀 1A 2A 3A 200mA Lipo LiFe 충전기 100-240v AC 밸런스 충전기 30W, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=unknown, 1645939516980, productName=얇은 명주 그물 롤 6 ''* 25 야드 오간자 스풀 투투 스크랩북 용품 웨딩 DIY 파티 베이비 샤워 장식, displayProductName=얇은 명주 그물 롤 6 ''* 25 야드 오간자 스풀 투투 스크랩북 용품 웨딩 DIY 파티 베이비 샤워 장식, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=베스트상품, 1618833927188, productName=로고 재떨이 LED 조명등나푸른 조명등 아우디 A1 A3 A4 A5 A6 Q3 Q5 8V Q7 C5 B8 A8, displayProductName=로고 재떨이 LED 조명등나푸른 조명등 아우디 A1 A3 A4 A5 A6 Q3 Q5 8V Q7 C5 B8 A8, generalProductName=로고 재떨이 LED 조명등나푸른 조명등 아우디 A1 A3 A4 A5 A6 Q3 Q5 8V Q7 C5 B8 A8, manufacture=베스트선정아이템");
        candidateList.add("Brand=unknown, 1652234724854, productName=GS GR D25L30 2 조 샤프트 커플러 알루미늄 모터 플렉시블 커플 링 커넥터 CNC 4566.3581012mm, displayProductName=GS GR D25L30 2 조 샤프트 커플러 알루미늄 모터 플렉시블 커플 링 커넥터 CNC 4566.3581012mm, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=협력업체, 1645855782370, productName=16S 58.4V 4A 지능형 배터리 충전기 48V 51.2V-52VLifePO4 배터리 팩 전기 자전거 스쿠터 빠른 스마트 충전기, displayProductName=16S 58.4V 4A 지능형 배터리 충전기 48V 51.2V-52VLifePO4 배터리 팩 전기 자전거 스쿠터 빠른 스마트 충전기, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=unknown, 1654264903074, productName=Juki-노즐 SMT 픽 앤 플레이스 머신 Juki 노즐 코어 500501502503504505506507508509510 511 픽앤플레이스, displayProductName=Juki-노즐 SMT 픽 앤 플레이스 머신 Juki 노즐 코어 500501502503504505506507508509510 511 픽앤플레이스, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=unknown, 1653453595228, productName=버트 캡/짐벌 커버 16 #/20 #/23.5 #/25 #/27.5 #/30 # 소프트 캡 낚싯대 엔드, displayProductName=버트 캡/짐벌 커버 16 #/20 #/23.5 #/25 #/27.5 #/30 # 소프트 캡 낚싯대 엔드, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=베스트상품, 1616642657140, productName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, displayProductName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, generalProductName=포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, manufacture=베스트선정아이템");
        candidateList.add("Brand=베스트상품, 1624276560509, productName=60mm 바퀴  20개 236인치 림  캡 커버 BMW 도요타 포드 혼다 현대 베이직 허브 모자, displayProductName=60mm 바퀴  20개 236인치 림  캡 커버 BMW 도요타 포드 혼다 현대 베이직 허브 모자, generalProductName=60mm 바퀴  20개 236인치 림  캡 커버 BMW 도요타 포드 혼다 현대 베이직 허브 모자, manufacture=베스트선정아이템");
        candidateList.add("Brand=트윈, 1651686687199, productName=캔버스 리본 폴리에스터 코튼 웨빙 스트랩 10 m 30mm 너비 바느질 가방 벨트 액세서리 DIY 공예, displayProductName=캔버스 리본 폴리에스터 코튼 웨빙 스트랩 10 m 30mm 너비 바느질 가방 벨트 액세서리 DIY 공예, generalProductName=, manufacture=트윈");
        candidateList.add("Brand=협력업체, 1649150770618, productName=12 V 50.4V 1.5A 2A 지능형 리튬 배터리 충전기 43.2V 43.8V 44.4V 48V Lypomer 리튬 이온 배터리 팩, displayProductName=12 V 50.4V 1.5A 2A 지능형 리튬 배터리 충전기 43.2V 43.8V 44.4V 48V Lypomer 리튬 이온 배터리 팩, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=협력업체, 1645854185381, productName=양쯔강 50.4V 4A 리튬 이온 배터리 충전기 12S 44.4V Lipo 자전거 전원 도구 스쿠터 배터리 팩 CE ROHS, displayProductName=양쯔강 50.4V 4A 리튬 이온 배터리 충전기 12S 44.4V Lipo 자전거 전원 도구 스쿠터 배터리 팩 CE ROHS, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=협력업체, 1645852671231, productName=양쯔강 14.6V 20A Lifepo4 리튬 배터리 충전기 12V 20A 전기 자전거 스쿠터 전자 자전거 전기 도구 전원 공급 장치, displayProductName=양쯔강 14.6V 20A Lifepo4 리튬 배터리 충전기 12V 20A 전기 자전거 스쿠터 전자 자전거 전기 도구 전원 공급 장치, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=베스트상품, 1624279675168, productName=림 236인치 바퀴 60mm 20개  캡 커버 BMW 도요타 포드 혼다 현대 베이직 허브 모자, displayProductName=림 236인치 바퀴 60mm 20개  캡 커버 BMW 도요타 포드 혼다 현대 베이직 허브 모자, generalProductName=림 236인치 바퀴 60mm 20개  캡 커버 BMW 도요타 포드 혼다 현대 베이직 허브 모자, manufacture=베스트선정아이템");
        candidateList.add("Brand=베스트상품, 1622198775322, productName=인기  포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, displayProductName=인기  포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, generalProductName=인기  포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, manufacture=베스트선정아이템");
        candidateList.add("Brand=협력업체, 1654465615842, productName=YZPOWER 자동 정지 84V 4A 리튬 배터리 충전기 72V 리튬 이온 Lipo 배터리 팩 Ebike 전자 자전거 스마트 충전기, displayProductName=YZPOWER 자동 정지 84V 4A 리튬 배터리 충전기 72V 리튬 이온 Lipo 배터리 팩 Ebike 전자 자전거 스마트 충전기, generalProductName=, manufacture=협력업체");
        candidateList.add("Brand=unknown, 1654471674985, productName=새로운 여성 수영 모자 소녀 긴 머리 입욕 스트레치 드레이프 풀 해변 수상 스포츠 탄성 나일론 터번, displayProductName=새로운 여성 수영 모자 소녀 긴 머리 입욕 스트레치 드레이프 풀 해변 수상 스포츠 탄성 나일론 터번, generalProductName=, manufacture=unknown");
        candidateList.add("Brand=베스트상품, 1624276279831, productName=알루미늄 56cm  20X 56mm 휠  데칼 BMW 도요타 혼다 현대 재규어 지프 닛산 볼보, displayProductName=알루미늄 56cm  20X 56mm 휠  데칼 BMW 도요타 혼다 현대 재규어 지프 닛산 볼보, generalProductName=알루미늄 56cm  20X 56mm 휠  데칼 BMW 도요타 혼다 현대 재규어 지프 닛산 볼보, manufacture=베스트선정아이템");
        candidateList.add("Brand=베스트상품, 1622198775322, productName=인기  포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, displayProductName=인기  포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, generalProductName=인기  포드/도요타/BWM/벤츠 범용 확장 머드 플랩 스크류 클립 라이닝 도어 패널 버클, manufacture=베스트선정아이템");

        List<String> shuffleList = new ArrayList<>();
        for (int i = 0; i < 14928; i++) {
            Collections.shuffle(candidateList);
            for (String candidate : candidateList) {
                shuffleList.add(new String(candidate));
            }
        }

        return shuffleList.subList(0, 100);
    }

}
